package com.dengxiujun.simpletomcat.container;

import com.dengxiujun.simpletomcat.config.ServletMappingConfig;
import com.dengxiujun.simpletomcat.handler.NIOConnectionHandler;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * <p></p>
 *
 * @author dengxiujun
 * @date 2021-04-26
 **/
public class NIOServletContainer {

    private int port;

    public NIOServletContainer(int port) {
        this.port = port;
    }
    
    private int count = 0;

    public void start() {
        ServletMappingConfig.initServletMapping();
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        try (Selector selector = Selector.open();
             ServerSocketChannel ssc = ServerSocketChannel.open()) {
            ssc.configureBlocking(false);
            ssc.socket().bind(new InetSocketAddress(port));
            ssc.register(selector, SelectionKey.OP_ACCEPT);

            System.out.println("NIO Tomcat 容器启动成功!");
            while (true) {
                int readyChannels = selector.select();
                if(readyChannels == 0) continue;
                Iterator<SelectionKey> it = selector.selectedKeys().iterator();
                while (it.hasNext()) {
                    SelectionKey sk = it.next();
                    count++;
                    it.remove();
                    System.out.println("第" + count + "次请求!");
                    SocketChannel sc = ((ServerSocketChannel) sk.channel()).accept();
                    executorService.execute(new NIOConnectionHandler(sc));
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            executorService.shutdown();
        }
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

}
